package deepr.src.pg;

import com.alibaba.fastjson.JSONObject;
import deepr.anno.SchemaType;
import deepr.core.DisposeContext;
import deepr.core.SchemaData;
import deepr.core.SchemaManager;
import deepr.db.GraphMapper;
import deepr.db.PgMapper;
import deepr.exception.DeeprAssert;
import deepr.lib.*;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.apache.logging.log4j.message.ReusableMessage;
import org.neo4j.driver.Record;
import org.neo4j.driver.internal.value.ListValue;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.activation.MailcapCommandMap;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

@Data
@NoArgsConstructor
@Slf4j
public class MatchForeignData {

  private Class<?> primaryKeyCzz;
  private String foreignName;
  private String primaryKey;
  private SchemaType schemaType;
  private Class<?> schemaCzz;
  private SchemaData schemaData;
  private int i = 0;
  private String[] select;
  private Object newArray;
  private String object;
  private List<Map<String, Object>> result;
  private List<Record> graphResult;


  public MatchForeignData(String foreignName, Class<?> schemaCzz, String primaryKey, String[] select, int size) throws NoSuchFieldException {
    Field field = schemaCzz.getDeclaredField(primaryKey);
    this.primaryKeyCzz = field.getType();
    this.primaryKey = primaryKey;
    this.foreignName = foreignName;
    this.object = foreignName;
    this.select = select;
    this.schemaCzz = schemaCzz;
    this.schemaData = SchemaManager.getSchemaData(schemaCzz);
    this.schemaType = schemaData.getSchemaType();
    newArray = Array.newInstance(primaryKeyCzz, size);
  }

  public void queryDb(DisposeContext ctx) throws Exception {
    Map<String, Object> filter = new HashMap<>();
    filter.put(primaryKey, newArray);
    String name = schemaData.getName();
    SchemaType schemaType = schemaData.getSchemaType();
    String table = PgQlLib.getTableName(schemaData, ctx, name);
    String selectStr;
    switch (schemaType) {
      case PG:
        selectStr = PgQlLib.parseSelectKeys(ctx, schemaData.getFields(), object, select);
        String str = "SELECT " + selectStr + " FROM " + table + " WHERE " + primaryKey + " = any(#{" + primaryKey + "})";
        log.debug("matchStr: {}, filter: {}", str, JSONObject.toJSON(filter));
        List<Map<String, Object>> list = ((PgMapper) ctx.getDeeprMapper()).queryList(str, filter);
        result = list;
        break;
      case NEO4J:
        selectStr = FilterLib.parseSelectKeys(ctx, schemaData.getFields(), object, select);
        str = "MATCH (" + object + ":" + table + ") WHERE " + object + "." + primaryKey + " IN $" + primaryKey + "" +
            " WITH {" + selectStr + "} AS " + object + " return " + object;
        GraphMapper graphMapper = SpringUtils.getBean("neo4jDb");
        DeeprAssert.isTrue(graphMapper != null, "get Bean neo4jDb failed");
        List<Record> records = graphMapper.queryList(str, filter);
        graphResult = records;
        break;
      default:
        break;
    }
  }


  public void setArrayNth(Object v) {
    Array.set(newArray, i, v);
    i++;
  }

}
